package org.kwisatz.proxybot.filters;

import java.awt.GridLayout;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.StringTokenizer;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.kwisatz.proxybot.FilterAdapter;
import org.kwisatz.proxybot.Message;

public class Voila extends FilterAdapter
{
	private static final String BASE_URL = "http://tchat.voila.fr";

	public static void main(String[] args)
	{
		try
		{
			//args=new String[]{"totw9AQE"};
			if(args.length<1)
			{
				System.out.println("Syntax: registrer <nick name>");
			}
			else
			{
				Voila r = new Voila();
				r.nickName = args[0];
				System.out.println(r.register());
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	private HttpClient client = new HttpClient();
	private transient URL imageURL;
	private transient String key, code, code1, code2;
	private String nickName;

	private boolean endRegistration() throws IOException
	{		
		PostMethod post = new PostMethod(BASE_URL + '/' + "v4authClientLourd3.php");
		post.addRequestHeader("Content-Type",
			"application/x-www-form-urlencoded");
		post.setRequestEntity(new StringRequestEntity("clef=" + key + "&nick="
			+ nickName + "&sexe=&age=&ville=&code1=" + code1 + "&code2="
			+ code2 + "&code=" + code + "&x=23&y=9"));
		client.executeMethod(post);
		Header location = post.getResponseHeader("location");
		return location==null;		
	}

	/**
	 * Find a line, cut it on quotes and retreive a word
	 * @param in the reader to search
	 * @param linePattern a pattern to find the line were to get the word
	 * @param index the index of the word in the line
	 * @return
	 * @throws IOException
	 */
	//TODO rewrite using jtidy
	private static String getPattern(BufferedReader in, String linePattern, int index)
		throws IOException
	{
		String line = in.readLine();		
		while (line != null && !line.contains(linePattern))
			line = in.readLine();

		if(line == null)
			return null;
		
		StringTokenizer tokernizer = new StringTokenizer(line, "\"");

		for (int i = 0; i < index; i++)
			tokernizer.nextToken();
			
		return tokernizer.nextToken();
	}

	private static boolean isVoilaServer(String serverHost) {
		return "irc.voila.fr".equals(serverHost) ||
			(serverHost.endsWith(".x-echo.com") &&
			serverHost.startsWith("chat"));
	}

	/**
	 * Helper post method
	 * @return A reader on the body response
	 * @throws IOException
	 * @throws HttpException
	 */
	private BufferedReader postRequest(String relativeURL, String query)
		throws IOException
	{
		PostMethod post = new PostMethod(BASE_URL + '/' + relativeURL);
		post.addRequestHeader("Content-Type",
			"application/x-www-form-urlencoded");
		post.setRequestEntity(new StringRequestEntity(query));
		client.executeMethod(post);
		return new BufferedReader(new InputStreamReader(
			post.getResponseBodyAsStream()));
	}

	public String register() throws IOException
	{
		retreiveKey();
		retreiveImageURL();
		while(showDialg() && !endRegistration());
		return key;
	}

	private void retreiveImageURL() throws IOException
	{
		String encodedKey=key;
		try
		{
			encodedKey = URLEncoder.encode(key, "UTF-8");
		}
		catch (UnsupportedEncodingException e)
		{
			e.printStackTrace();
		}
		
		BufferedReader in = postRequest("v4authClientLourd2.php", "cgu=1&clef="
			+ encodedKey + "&nick=" + nickName);
		// +"&x=23&y=9&form_destination=v4authClientLourd2.php&1=1");

		// <input type="hidden" name="code1" value="434913" />
		code1 = getPattern(in, "name=\"code1\" value=\"", 5);
		code2 = getPattern(in, "name=\"code2\" value=\"", 5);
		String img = getPattern(in, "alt=\"Code de contr", 1);
		imageURL = new URL(BASE_URL + img);
	}

	private void retreiveKey() throws IOException
	{
		PostMethod post = new PostMethod(BASE_URL + "/v4authClientLourd2.php");
		post.addRequestHeader("Content-Type",
			"application/x-www-form-urlencoded");
		post.setRequestEntity(new StringRequestEntity("nick=" + nickName));
		client.executeMethod(post);

		Header location = post.getResponseHeader("location");
		if (location != null && location.getValue().endsWith("16"))
		{
			throw new IOException("Ce pseudo est deja utilise, veuillez "+
				"choisir un autre pseudo, puis valider.");
		}

		// look for the key in the response
		BufferedReader in = new BufferedReader(new InputStreamReader(
			post.getResponseBodyAsStream()));
		key = getPattern(in, "<input type=\"hidden\" name=\"clef\" value=\"", 5);
	}

	public void setNickName(String nickName)
	{
		this.nickName = nickName;
	}

	private boolean showDialg() 
	{
		JLabel label = new JLabel(new ImageIcon(imageURL));
		JTextField field = new JTextField();
		JPanel panel = new JPanel();
		panel.setLayout(new GridLayout(1, 2));
		panel.add(label);
		panel.add(field);
		
		int r = JOptionPane.showConfirmDialog(null, panel, "Control code",
			JOptionPane.CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
		
		if (r == JOptionPane.YES_OPTION)
		{
			code = field.getText();
			return true;
		}
		else
		{
			return false;
		}
	}
	
	private boolean loginInProgress=true;
	private String nickLine;
	private String userLine;
	
	@Override
	public String handleClientLine(String line, Message message)
	{		
		if(loginInProgress && isVoilaServer(context.getServerHost())) 
		{			
			if(line.startsWith("NICK"))
			{
				nickLine=line;				
			}
			else if(line.startsWith("USER"))
			{
				userLine=line;
			}
			
			if(nickLine!=null && userLine!=null)
			{
				Voila r = new Voila();
				r.nickName = context.getNickName();
				try
				{
					String k=r.register();
					context.getServer().println("PASS "+ k);
					context.getServer().println(nickLine);
					context.getServer().println(userLine);
					loginInProgress=false;
				}
				catch(IOException ex)
				{
					ex.printStackTrace();
					ex.printStackTrace(clientNotice);
				}
			}
			return null;
		}
		else
			return line;
	}	
}
